﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;


/************
 * 
 * **************/
namespace EJServer_driver
{
    public class EJDriver
    {
        //this class is used to send and recieve messages from message-based device and process is then hand to EJserver
        //this is also a template to make you own drivers
        //you1don't have to follow the whole structrue
        //for detials and which function is critical look for the document

        const int OUTMSG_TIMEOUT = 50;

        private bool IsByte;    //if the cmd is byte or string
        private int CMDLen; //the lenth of the cmd used in byte cmd
        private byte CMDEnd;    //the end char  of the cmd used in byte cmd

        public  delegate void MSGArrivedHandler(byte[] MyMessage);
        MSGArrivedHandler MsgArrived = null;    //listenner will invoke this when message arived


        //call the message Arrived function in EJServer not this class
        public delegate void SendToEJServerHandler(byte[] MyMessage);
        public SendToEJServerHandler SendtoEJServer;                       

        public delegate void ListenerHandler();
        ListenerHandler MyListener=null;

        Thread ListenerThread;  //the listener thread

        //async call the out message ,couse you will not know when willit return
        public delegate int OutMSGHandler(byte[] MyMessage);
        OutMSGHandler OutMSG = null;

        
        public EJDriver(bool isByte,int len,byte end,object IniObj)
        {
            // MyListener = new ListenerHandler(Listener);
            //len and end is for byte message
            OutMSG = new OutMSGHandler(Out_msg);
            MsgArrived = new MSGArrivedHandler(MessageArrived);
        }

        public void IinDriver(SendToEJServerHandler SendtoEJS)
        {
            SendtoEJServer  = SendtoEJS ;
            this.StartListener();
            //start listener here
        }

        public void StopDriver()
        {
            ListenerThread.Suspend();
        }

        #region send the message

        public  int Send_msg(string message_str)
        {
            byte [] message;
            message = Proc_msg(message_str);
            IAsyncResult ASResult = OutMSG.BeginInvoke(message, null, null);
            if (ASResult.AsyncWaitHandle.WaitOne(OUTMSG_TIMEOUT, false) == true)
            {
                //use end invoke to get the return value of the outmsg
                //return 0;
                return OutMSG.EndInvoke(ASResult);
            }
            else
            {
                return -1;  //timeout
            }
                //return 0;   //returns the status ,if the message is successfully send out   //called by EJServer
        }

        public  int Send_msg(byte[] message_byte)
        {
            byte[] message;
            message = Proc_msg(message_byte);
            IAsyncResult ASResult = OutMSG.BeginInvoke(message, null, null);
            if (ASResult.AsyncWaitHandle.WaitOne(OUTMSG_TIMEOUT, false) == true)
            {
                return 0;
            }
            else
            {
                return -1;  //timeout
            }
            //return 0;   //returns the status ,if the message is successfully send out //called by EJServer
        }

        private static byte[] Proc_msg(string messager_str)
        {
            //proccess the message tobe sent
            //test code
            Encoding my_ASC = Encoding.ASCII;
             return my_ASC.GetBytes(messager_str);
        }

        private static byte[] Proc_msg(byte[] messager_byte)
        {
            //proccess the message tobe sent
            //test code
            return messager_byte ;
        }

        private static int Out_msg(byte[] MyMessage)
        {
            //send the message out via hardware
            //return send status
            Encoding my_ASC = Encoding.ASCII;
            string msgStr = my_ASC.GetString(MyMessage);
            Console.WriteLine(msgStr+msgStr.Length.ToString());
            return 0; 
        }


        #endregion

        #region recieve message

        private static  byte[] Proc_MSG_In(byte[] myMessage)
        {
            //proccess the incoming message
            return myMessage ;
        }

        private void MessageArrived(byte[] MyMessage)
        {
            //listenner will invoke this when got message
            if (SendtoEJServer != null)
            {
                SendtoEJServer(Proc_MSG_In(MyMessage));
            }
        }



        #endregion


        #region linstening

        public void StartListener()
        {   //start the listener
            if (ListenerThread == null)
            {
                ListenerThread = new Thread(new ThreadStart(this.Listener));
                ListenerThread.Start();
            }
            else 
            {
                try
                {
                    ListenerThread.Start();
                }
                catch
                {
                    throw new System.Exception("Can not start ListenerThread");
                }
            }
        }


        private  void Listener()
        {
            byte [] recievBuffer=new byte[1024];
            while (true)
            {
                //listening
                //when meeage com invoke proc it and invoke MsgArv
                #region testcode
                try
                {

                    string mytestStr;
                    mytestStr = Console.ReadLine(); //normally will use a block function
                    Encoding my_ASC = Encoding.ASCII;
                    recievBuffer = my_ASC.GetBytes(mytestStr);
                    MsgArrived.BeginInvoke(recievBuffer,null,null);
                }
                finally
                {
                    //nothing
                }
	            #endregion
                
            }
        }

        #endregion




    }
}
